package gg.zsw.dataframework.pubsub;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;

/**
 * 在实时系统中，有以下特征
 * 1. 数据的处理原则常常是过期不候，所以用环形队列进行缓存
 * 2. 多数据之间需要同步，所以需要反查机制，推和拉的方式都需要支持
 *
 * @author zhou.sw
 * @Date 2020/6/29 11:52
 */
public abstract class AbsSequentialSubject<Observer extends AbstractObserver<NotifyData>, NotifyData>
        extends AbstractSubject<Observer, NotifyData> {

    @Setter
    private int cacheNum = 10;

    /**
     * Object类型，才可以new出这个数组。
     */
    private Object[] caches;

    public AbsSequentialSubject() {
        caches = new Object[cacheNum];
    }

    public AbsSequentialSubject(int cacheNum) {
        this.cacheNum = cacheNum;
        caches = new Object[cacheNum];
    }

    /**
     * 发出通知前，先缓存一下
     *
     * @param notifyData
     */
    @Override
    protected void beforeNotify(NotifyData notifyData) {
        long time = getNotifyDataTime(notifyData);
        int index = (int) (time % cacheNum);
        caches[index] = notifyData;
    }

    /**
     * 拉取指定时间的数据
     *
     * @param time
     * @return 取不到时返回null
     */
    public NotifyData getNotifyData(long time) {
        int index = (int) (time % cacheNum);
        NotifyData notifyData = (NotifyData) caches[index];
        if (notifyData != null && getNotifyDataTime(notifyData) == time) {
            return notifyData;
        }
        return null;
    }

    public abstract long getNotifyDataTime(NotifyData notifyData);

}
